package org.tio.sitexxx.web.server.controller.minip;

import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.server.annotation.RequestPath;
import org.tio.sitexxx.im.server.ws.ImWsMsgHandler;
import org.tio.sitexxx.service.model.main.*;
import org.tio.sitexxx.service.service.qj.*;
import org.tio.sitexxx.service.vo.Const;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequestPath(value = "/kf")
public class kf_order {
    private static Logger log = LoggerFactory.getLogger(kf_order.class);
    private static  String db = Const.Db.TIO_SITE_MAIN;

    /**
     * 订单初始化
     * @param request
     * @return
     */
    @RequestPath(value = "/pay/init")
    public Map<String, Object> pay_init(HttpRequest request){//支付金额,用户openid,
        Map<String,Object>map= JSON.parseObject(request.getBodyString());
        Integer pay_amount=Integer.parseInt(map.get("pay_amount").toString());//支付金额
        String openid=map.get("openid").toString();//用户openid
        Map<String,Object>temp=new HashMap<>(3);
        temp.put("openid",openid);
        Member member=MemberService.me.getMember(temp);
        int consult_id=Integer.valueOf(map.get("id").toString());

        Date time=new Date();//其实因该在数据库里设置默认值

        String orderid="kf-"+consult_id+"-"+System.currentTimeMillis()+"";//订单号
        Record paymemt=new Record().set("orderid",orderid).set("pay_amount",pay_amount).set("amount",pay_amount)
                .set("type","kf").set("createdAt",time).set("memberId",member.getId())
                .set("is_paid",0).set("updatedAt",time).set("consultant_member_id",consult_id);
        Db.use(Const.Db.TIO_SITE_MAIN).save("payment","id",paymemt);
        int payment_id=Integer.valueOf(paymemt.get("id").toString());
        return PayParameters.payParameters.Parameters(openid,pay_amount,orderid,payment_id,log,"kf",0);
    }

    /**
     * 用户不点完成无法触发  这时微信调用callback
     * @param request
     * @return
     */
    @RequestPath(value="/pay/submit")
    public Object kf_submit(HttpRequest request){
        Map<String,Object>body= JSON.parseObject(request.getBodyString());
        Map<String ,Integer>map=new HashMap<>(2);
        Integer result=0;
        String str="";
        try{
            String order=body.get("order_id").toString();
            /*result=skipDao.update_payment(order);*/
            Integer consultant_id=Integer.valueOf(body.get("consultant_id").toString());
            String openid=body.get("openid").toString();
            String types=order.split("-")[0];//截取订单前缀类型
            Db.update("update payment set is_paid=1 where orderid=?",order);
            str=update_status(types,openid,consultant_id);
        }catch (NullPointerException e){
            log.error(e.toString(),e);
            System.out.println(e.getMessage()+"/kf/pay/submit");
            map.put("status",0);
        }catch (Exception e){
            log.error(e.toString(),e);
            System.out.println(e.getMessage()+"/kf/pay/submit");
            map.put("status",0);
        }
        if(str.equals("ok")){
            result=1;
        }
        System.out.println("result:"+result);
        map.put("status",result);
        return map;
    }

    public String  update_status(String types,String openid,Integer consultant_id){
        type str_type= type.getTypeByValue(types);
        String str="";
        switch (str_type){
            case kf:
                str=kf_status(openid,consultant_id);
                break;
            case zx:
                break;
        }
        return str;
    }

    /**
     *功能函数，抛出异常却没有做处理，解释一下 此功能函数只在支付成功之后才有可能被调用
     * 该异常只在158行有可能抛出，但不可能发生因为都已经支付成功了
     * @param openid
     * @param consultant_id
     * @return
     * @throws NullPointerException
     */
    public String kf_status(String openid,Integer consultant_id) throws  NullPointerException{

        Map<String,Integer> mId = SkipService.me.findMId(openid);//用户id
        Integer id=mId.get("id");
        Map<String,Integer> cmId=SkipService.me.isSaveValid(id,consultant_id);
        System.out.println("cmid:"+JSON.toJSONString(cmId));
        if(cmId==null){
            Record consultantmembervalid=new Record().set("expired",1).set("member_id",id)
                    .set("consultant_id",consultant_id);
            Db.use(db).save("consultant_member_valid",consultantmembervalid);
        }else{
            boolean res = SkipService.me.updateValidTime(1,id,consultant_id);
            System.out.println("insert result:"+res);
        }
        return "ok";
    }

    /**
     * 微信callback，是微信作为第一方调用我们的此接口，用于确认支付是否成功，此接口若出现异常，会出现反复被调用的状况
     * 参github上wxjava开源项目，那里有详细的demo
     * @param request
     * @param response
     * @return
     */
    @RequestPath(value="/pay/callback")
    public String  payNotify(HttpRequest request, HttpResponse response) {
        try {
            String xmlResult = IOUtils.toString(request.getBody(), request.getCharset());
            WxPayOrderNotifyResult result = wxpay.getInstance().parseOrderNotifyResult(xmlResult);
            // 结果正确
            String openid=result.getOpenid();
            String orderId = result.getOutTradeNo();
            String tradeNo = result.getTransactionId();
            String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            double fee=Double.valueOf(totalFee);
            System.out.println("orderid"+orderId+"tradeNo"+tradeNo+"totalfee"+totalFee);
            //自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
            String types=orderId.split("-")[0];//截取订单前缀类型
            System.out.println("order type is:"+types);
            type str_type=type.getTypeByValue(types);
            switch (str_type){
                case zx:

                    break;
                case kf://咨询客服

                    Db.use(Const.Db.TIO_SITE_MAIN).update("update payment set is_paid=1 where orderid=?",orderId);
                    Integer consultant_id=Integer.valueOf(orderId.split("-")[1]);//截取客服id
                    kf_status(openid,consultant_id);//更新截止时间
                    break;
                case c://余额充值

                    Db.use(Const.Db.TIO_SITE_MAIN).update("update payment set is_paid=1 where orderid=?",orderId);
                    callback_charge(orderId);
                    break;
                case q://一元提问

                    Db.use(Const.Db.TIO_SITE_MAIN).update("update payment set is_paid=1 where orderid=?",orderId);
                    Integer question_id=Integer.valueOf(orderId.split("-")[2]);//截取问题id
                    System.out.println("q callback:"+question_id);
                    QuestionService.me.update_is_paid(question_id,true);
                    callback_question(orderId);
                    break;
                case w://私人衣橱

                    Integer wardrobe_id=Integer.valueOf(orderId.split("-")[2]);//截取衣橱id
                    Db.use(Const.Db.TIO_SITE_MAIN).update("update payment set is_paid=1 where orderid=?",orderId);
                    callback_wardrobe(orderId,openid,wardrobe_id);
                    break;
            }
            return WxPayNotifyResponse.success("处理成功!");
//            writeMessageToResponse(response,"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");//原springboot下
        } catch (Exception e) {
//            e.printStackTrace();
            log.error(e.toString(), e);
            System.out.println("weixin callback error:"+e.getMessage());
            return WxPayNotifyResponse.fail(e.getMessage());
//           writeMessageToResponse(response,"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
        }

    }

    /**
     * 废弃，tio框架不支持servlet
     * @param response
     * @param message
     */
    protected void writeMessageToResponse(HttpServletResponse response,String message){//测试解决微信失败时候多次回调
        PrintWriter printWriter=null;
        try {
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            printWriter=response.getWriter();
            printWriter.write(message);
            printWriter.flush();
        }catch (IOException e){
            e.printStackTrace();
        }finally{
            if(printWriter!=null){
                printWriter.close();
            }
        }
    }
    public  void beanToMap(Map<String, Object> res, Object object) throws Exception {

        Class cls = object.getClass();//getclass()返回一个对象类型   通过cls可以获得获得该对象的所有对象和方法
        Field[] fields = cls.getDeclaredFields();//得到的是该类自己声明的成员变量的信息
        for (Field field : fields) {
            field.setAccessible(true);
            if(field.get(object)!=null)
                res.put(field.getName(), field.get(object));//field.getName()得到成员变量名
        }

    }

    /**
     * 原本是支付成功后paysubmit接口里的东西，
     * 但是由于用户支付后不点击完成按钮无法调用paysubmit接口 故将其写到这边来
     * 代码有些累赘 但是只能这么写，下同
     * @param orderId
     */
    public void callback_charge(String orderId){
        Map<String,Object>map=new HashMap<>(2);
        map.put("orderId",orderId);
        Payment Payment = PaymentService.me.getPayment(map);
        Charge ChargeController = ChargeService.me.getCharge(Payment.getChargeId());
        map.put("id",Payment.getMemberId());
        Member Member = MemberService.me.getMember(map);
        if(ChargeController==null){//临时
            Member.setBalance(Member.getBalance()+Payment.getPayAmount());
            Member.update();
            return;
        }
        //余额为支付金额加优惠 当达不到优惠金额时 优惠为0
        int gold = Payment.getPayAmount() + ((Payment.getPayAmount()>=ChargeController.getThreshold())?ChargeController.getReward() : 0);
        //更新余额
        Member.setBalance(Member.getBalance()!=null?Member.getBalance() + gold : gold);
        System.out.println("balance:"+Member.getBalance());
        MemberService.me.update(Member);
    }

    /**
     * 同上
     * @param orderId
     */
    public void callback_question(String orderId){
        Map<String,Object>map=new HashMap<>(2);
        map.put("orderId",orderId);
        Payment Payment = PaymentService.me.getPayment(map);

        Coupon Coupon;
        if (Payment.getCoupon() != null) {
            Coupon = CouponService.me.getCouponById(Payment.getCoupon());
        } else {
            System.out.println("no coupons");
            Coupon = null;
        }

        if (Coupon != null) {
            Coupon.setStatus((short)3);
            CouponService.me.update(Coupon);
        }
    }

    /**
     * 同上
     * @param orderId
     */
    public void callback_wardrobe(String orderId,String openid,int wardrobe_id){
        Map<String,Object>map=new HashMap<>(2);
        map.put("openid", openid);
        Member Member = MemberService.me.getMember(map);
        System.out.println(JSON.toJSONString("wardrobe_id:"+wardrobe_id));
        List<Wardrobe> Wardrobes = WardrobeService.me.getWardrobes_(wardrobe_id,Member.getId());

        Map<String,Object>temp=new HashMap<>(2);
        temp.put("orderId",orderId);
        Payment Payment = PaymentService.me.getPayment(temp);
        Coupon Coupon;

        if (Payment.getCoupon() != null) {
            Coupon = CouponService.me.getCouponById(Payment.getCoupon());
        } else {
            Coupon = null;
        }

        if (Coupon != null) {
            Coupon.setStatus((short)3);
            CouponService.me.update(Coupon);
        }
        for (int i = 0; i < Wardrobes.size(); i++) {
            Wardrobes.get(i).setPaid(true);
            WardrobeService.me.update(Wardrobes.get(i));
        }
        Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                Member.setShow((byte)1);
                MemberService.me.update(Member);
                return true;
            }
        });
    }
}
